﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using CRM.Extensions;
using CRM.Models;
using CRM.Models.Email;
using CRM.Services;
using CRM.Services.Email;
using CRM.Services.SystemManage;
using CRM.ViewModels.Email;
using Mailjet.Client;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using Z.EntityFramework.Plus;

namespace CRM.Controllers.Email
{
    [Route("api/[controller]")]
    [ApiController]
    public class EmailMarketingController : BaseController
    {
        private readonly MyDbContext _dbContext;
        private readonly ILogger<MailjetApplicationService> _logger;
        private readonly IMailjetClient _mailjetClient;
        private readonly UserManager<User> _userManager;
        private readonly CompanyService _companyService;
        private readonly CompanyPointsConfigService _companyPointsConfigService;
        private readonly EmailMarketingService _emailMarketingService;

        public EmailMarketingController(MyDbContext dbContext, ILogger<MailjetApplicationService> logger,
            IMailjetClient mailjetClient, UserManager<User> userManager, CompanyService companyService,
            CompanyPointsConfigService companyPointsConfigService, EmailMarketingService emailMarketingService)
        {
            _dbContext = dbContext;
            _logger = logger;
            _mailjetClient = mailjetClient;
            _userManager = userManager;
            _companyService = companyService;
            _companyPointsConfigService = companyPointsConfigService;
            _emailMarketingService = emailMarketingService;
        }

        [HttpPost(nameof(Index))]
        public async Task<ResultStruct> Index(EmailMarketingListQuery query)
        {
            var user = await _userManager.GetUserAsync(User);
            var result =
                await _dbContext.EmailMarketing
                    .Where(m => m.OemId == user.OemId && m.CompanyId == user.CompanyId && m.GroupId == user.GroupId &&
                                m.UserId == user.Id)
                    .WhenWhere(query.Ids.IsNotNull(), m => query.Ids.Contains(m.Id))
                    .WhenWhere(!string.IsNullOrEmpty(query.Title),
                        m => m.Title.StartsWith(query.Title) || m.Title.EndsWith(query.Title))
                    .WhenWhere(query.State != 0 && query.State != null,
                        m => m.State == (EmailMarketing.StateEnum)query.State)
                    .WhenWhere(query.CreatedAt != null && query.CreatedAt.Length == 2,
                        m => m.CreatedAt >= query.CreatedAt[0] && m.CreatedAt <= query.CreatedAt[1].AddDays(1))
                    .OrderByDescending(m => m.Id)
                    .ToPaginateAsync(query.Page, query.Limit);
            return Success(result);
        }

        [HttpPost("[action]")]
        public async Task<ResultStruct> Create(EmailMarketingVM vm)
        {
            if (!ModelState.IsValid) return Error(message: ModelState.ToString());

            var customers = new Collection<Models.Customer>(vm.Addressee.Where(m => m.id != null)
                .Select(m => new Models.Customer() { Id = (int)m.id })
                .ToList());

            var result = await _emailMarketingService.Create(customers, vm);

            return result != null
                ? Success(new
                {
                    Model = result,
                    ReadUrls = result.AddresseeObj.Select(m =>
                        _emailMarketingService.BuildReadUrl(result.Id, m.Addressee))
                })
                : Error(message: _emailMarketingService.Error);
        }

        /// <summary>
        /// 搜索发件人名称
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        [HttpGet("[action]")]
        public async Task<ResultStruct> SearchSenderNames([FromQuery] string? name)
        {
            name = name is null ? name : name.Trim();
            var user = await _userManager.GetUserAsync(User);
            var names = await _dbContext.EmailSenderNames.Where(m => m.OemId == user.OemId && m.CompanyId == user.CompanyId && m.GroupId == user.GroupId && m.UserId == user.Id)
                .WhenWhere(!string.IsNullOrWhiteSpace(name), e => e.Name.Contains(name))
                .OrderByDescending(e => e.LatestUsedTime)
                .Select(e => new
                {
                    Value = e.Name,
                    Id = e.Id,
                })
                .ToArrayAsync();

            return Success(names);
        }

        [HttpPost("[action]")]
        public ResultStruct VerifyEmail([FromBody] JObject o)
        {
            // var email = (string) o["email"];
            // var client = new SmtpClient();
            // var _host = "smtp.gmail.com";
            // var port = 465;
            // client.ProxyClient = new Socks5Client("127.0.0.1", 7890);//走本地代理
            //  await client.ConnectAsync(_host, port, SecureSocketOptions.Auto, new CancellationToken());
            // await client.AuthenticateAsync("mo5467@126.com", "WNZWXABIIGIDLWB0", new CancellationToken());
            // var res = await client.VerifyAsync(email);
            // if (res.IsInternational)
            if (true)
            {
                var State = false;

                return Success(new { State });
            }
            else
            {
                //return Error(new {},"处理邮箱验证请求失败，请联系管理员");
            }
        }

        [HttpGet(nameof(Info))]
        public async Task<ResultStruct> Info([FromQuery] int id)
        {
            var user = await _userManager.GetUserAsync(User);
            var result = _dbContext.EmailMarketing
                .Where(m => m.OemId == user.OemId && m.CompanyId == user.CompanyId && m.GroupId == user.GroupId &&
                            m.UserId == user.Id)
                .Select(m => new
                {
                    m.Addressee,
                    m.Addresser,
                    m.Id,
                    m.OpenNum,
                    m.ReplyNum,
                    m.SendingNum,
                    m.SubmitNum,
                    m.Title,
                    m.State,
                    m.ReplyEmail,
                    m.EmailSubject,
                    m.Attachment,
                    m.EmailContent
                })
                .Single(s => s.Id.Equals(id));
            return Success(result);
        }

        [HttpGet("[action]")]
        public async Task<ResultStruct> ChangeState([FromQuery] int id)
        {
            var user = await _userManager.GetUserAsync(User);
            var result = await _dbContext.EmailMarketing
                .Where(m => m.OemId == user.OemId && m.CompanyId == user.CompanyId && m.GroupId == user.GroupId &&
                            m.UserId == user.Id)
                .Where(m => m.Id == id)
                .UpdateAsync(m => new() { State = EmailMarketing.StateEnum.Submitted });
            return result > 0 ? Success() : Error();
        }

        [HttpGet("InvokeEmailServerSend")]
        // public async Task InvokeEmailServerSend()
        public async Task InvokeEmailServerSend(int id)
        {
            var user = await _userManager.GetUserAsync(User);
            var email = await _dbContext.EmailMarketing
                .Where(m => m.OemId == user.OemId && m.CompanyId == user.CompanyId && m.GroupId == user.GroupId &&
                            m.UserId == user.Id).Where(m => m.Id == id).FirstAsync();
            var client = new MailjetApplicationService(_mailjetClient, _logger, _companyService,
                _companyPointsConfigService, _emailMarketingService);
            await client.RunAsync(email);
        }

        // [HttpPost(nameof(CreatEmailVerify))]
        // public async Task<ResultStruct> CreatEmailVerify(EmailVerifyVM vm)
        // {
        //     var user = await _userManager.GetUserAsync(User);
        //     if (!ModelState.IsValid) return Error(message: ModelState.ToString());
        //     var model = vm.NewModel(_dbContext,user);
        //     await _dbContext.EmailVerifies.AddAsync(model);
        //     await _dbContext.SaveChangesAsync();
        //     return Success();
        // }

        public record TimingTransmissionRecord(DateTime timeNew, DateTime timeOld, int id);

        /// <summary>
        ///  修改营销任务时间
        /// </summary>
        /// <param name="timingTransmissionRecord"></param>
        /// <returns></returns>
        [HttpPost("[action]")]
        public async Task<ResultStruct> EditTimingTransmission(
            [FromBody] TimingTransmissionRecord timingTransmissionRecord)
        {
            var timeNow = DateTime.Now;
            var (timeNew, _, id) = timingTransmissionRecord;
            if (timeNow.AddMinutes(2) > timeNew)
            {
                return Error(new object(), "时间过于接近或小于当前时间,已被禁止操作！");
            }

            var result = await _emailMarketingService.EditTimeTransmission(id, timeNew);
            return result ? Success() : Error(message: "修改发送时间失败");
        }

        /// <summary>
        /// 取消营销任务
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("[action]")]
        public async Task<ResultStruct> CancelEmailMarketingTask([FromQuery] int id)
        {
            var info = _emailMarketingService.GetInfoById(id);

            if (info == null)
            {
                return Error(message: "任务不存在");
            }

            if (info.State == EmailMarketing.StateEnum.Canceled || info.State == EmailMarketing.StateEnum.Completed)
            {
                return Error(message: "任务已经处于完成或取消状态");
            }

            if (info.IsLocked)
            {
                return Error(message: "任务处于锁定状态，无法取消");
            }

            var res = await _emailMarketingService.SetState(id, EmailMarketing.StateEnum.Canceled,
                EmailMarkeingLog.TypeEnum.Initiative, "取消营销任务");
            return res ? Success(message: "取消任务成功") : Error(message: "取消任务失败");
        }


        public record GetReadEmailsQuery(DateTime Time);
        /// <summary>
        /// 获取已读的收件箱
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        [HttpPost("[action]")]
        public async Task<ResultStruct> GetReadEmails(GetReadEmailsQuery query)
        {
            var user = await _userManager.GetUserAsync(User);
            var minDate = new DateTime(2024, 2, 26);
            var time = query.Time < minDate ? minDate : query.Time;
            var result =
                await _dbContext.EmailMarketing
                    .Where(m => m.OemId == user.OemId && m.CompanyId == user.CompanyId && m.GroupId == user.GroupId &&
                                m.UserId == user.Id)
                    .Where(m => m.Type == EmailMarketing.TypeEnum.Free && m.UpdatedAt >= time)
                    .ToListAsync();
            var emails = new HashSet<string>();
            foreach (var receiver in result.SelectMany(r => r.AddresseeObj))
            {
                if (receiver.IsRead)
                    emails.Add(receiver.Addressee);
            }
            return Success(emails);
        }
    }
}